MSYS2 介绍与使用

  • qq_36525177
  • 2023-01-09 08:22:41

    进入公司之后才使用的 msys2。感觉非常好用,速度比 Cygwin 更快,偶然看见这篇文章,便记录下来, 原文链接。后续如果有关于 msys2 的一些笔记,也会随时更新到这里。

    MYSYS2 前世今生

    Cygwin

    这一切得从源头说起, 1995 年 Cygnus 的一位工程师 Steve Chamberlain,他观察到 Windows 系统使用 COFF 作为目标文件 (即可执行文件) 格式,与此同时 GNU 的工具链已经支持 x86 和 COFF 的目标文件,并提供 C 语言库 newlib (Newlib 是嵌入式系统上的C标准库的实现) 。他认为既然 GNU 的工具链已经能够编译生成 x86 指令集的机器码并可链接生成 COFF 格式的目标文件, 而且还提供了可移植到任意平台的 C 标准库 newlib, 那么理论上只要将 GCC 重定向(根据对应目标平台重新编译), 作为一个 cross compiler (交叉编译器),那么这个 GCC 编译器不就可以生成 Windows 平台下的可执行文件了吗?事实证明这是可行的,Steve Chamberlain 很快开发出了原型, 并把他这个项目命名为 Cygwin。

    现在 GCC 工具链有了,终于可以使用熟悉的 GCC 而不是微软的那一套 MSVC 来生成 Windows 平台的应用程序了。不过,光有 GCC 并不能很好的进行构建工作, 还需要 shell 脚本解释器以及那些与 Uinx 系统配套的一系列称手的工具也加入进来,因为只有这些工具的加持,GCC 才能用得舒服。因此 Steve Chamberlain 的下一步工作是尝试在 Windows 构建 shell 脚本运行环境, 因此需要一个与 Bourne shell 兼容的命令解释器 (比如 bash), 而移植构建 shell 解释器需要一个 fork 系统来实现程序的调用和标准输入/输出。Windows 包含类似的功能, 但它们的接口和 POSIX 不兼容,这么一来 Cygwin 的库还需要提供与 POSIX 兼容的应用程序编程接口 (API)。为了达到这个目的 Cygwin 提供了一套抽象层 dll,用于将部分 Posix 调用转换成 Windows 的 API 调用,实现相关功能。这里面最典型的,最基本的模拟层就是那个 cygwin1.dll。

    这些工作早期都是由 Steve Chamberlain 一个人来完成, 但是到了 1996 年,由于看到 cygwin 可以提供 Windows 系统上的嵌入式工具链(以往的方案是使用 DJGPP),其他工程师也加入了进来。特别吸引人的是,Cygwin 可以实现 three-way cross-compile (第三方交叉编译),也就是说可以在远程工作站上使用 cygwin 来编译其他平台的代码, 而操作工作站的电脑只是一台普通的 pc, 该 pc 本身不编译代码。由于工作站的 CPU 普遍更为强大,这比在 PC 上使用 PC 的速度更快。1998 年起,Cygnus 开始将 Cygwin 包作为产品来提供。

    随着 Linux 系统的发展壮大,目前的 Cygwin 已经不仅仅提供 POSIX 兼容,因此也顺带多了更多模拟层的依赖关系。同时,由于它的模拟层实现了相当良好的 Posix 兼容,人们试着将许多重要的 Linux/BSD 应用移植到了Cygwin下,使得 Cygwin 越来越大,功能也越来越丰富,以至于目前很多人直接把将 Linux 应用移植到 Windows 平台的任务都交给了 Cygwin(当然,这种移植并非原生)。

    总结:从上面的描述可以看出, Cygwin 诞生之初,Steve Chamberlain 本来可能只是想通过 GCC 编译出 Windows 应用来,却因为 Posix 而顺带搞了一坨别的东西过来,最后发展到现在。可以说, Cygwin 是运行于 Windows 平台的 POSIX “子系统”,提供 Windows 下的类 Unix 环境,并提供将部分 Linux 应用“移植”到 Windows 平台的开发环境的一套软件。

    MinGW

    由于 Cygwin 的编译和调用方式总是需要依赖一层 POSIX 到 Windows API 的中间层, 比起日渐庞大的 Cygwin, 或许一个最小化且不需要中间层 GNU 工具链更能满足一些开发的需求, 于是 Colin Peters 在1998年创建了一个开源项目并撰写了最初的版本, 他将其命名为 mingw32 (Minimalist GNU for W32), 其意思就是 Windows 上的最小化 GNU 工具链, 这里的 Windows 被简称为 “W32”, 后来为了避免暗示它仅限于生成32位二进制文件, 后面的 32 被去除,从而变成了MinGW。

    在最初的版本,Colin Peters 首先为 MSVCRT。DLL (Microsoft Visual C Runtime) 库提供了一组头文件和一个导入库, 不过这些代码需要依赖和使用 Cygwin 的某些接口。之后的 Jan-Jaap van der Heijden 希望不再依赖于 Cygwin 库,而是仅仅使用本机的构建环境来构建应用程序,所以 Jan-Jaap 着手开发了 binutils、GCC 和 make,并生成了第一个无需使用 Cygwin 即可生成本机代码的编译器、汇编器和链接器工具。Mumit Khan 后来接手了开发工作,向程序包添加了更多 Windows 特定的功能,包括 Anders Norlander 的 Windows 系统标头。2000 年,该项目移至 SourceForge,以寻求社区的更多帮助并集中开发。 在 SourceForge 上得到了更多开源人士的帮助, MinGW 也得到很大的发展,甚至 2005 年 9 月 MinGW 被选为 SourceForge 的月度最佳项目。不过在与 SourceForge 对其邮件列表的管理存在分歧之后,2018年,MinGW 迁移到 OSDN。

    总结: MinGW 的出现是为了能够使用 GCC 工具链来构建不依赖于第三方运行库的应用程序, 相对于 Cygwin,它首要特点就是简单性和性能好,因此,它不提供某些不能使用 Windows API 轻松实现的 POSIX API,如 fork()、mmap() 和 ioctl()。而用 Cygwin 编写的 Windows 程序总是需要运行在兼容层 DLL 之上,因此该 DLL 必须与程序的源代码一起分发。MinGW 不需要兼容层,因为基于 MinGW 的程序是通过直接调用 Windows API 编译的。

    MYSYS

    MinGW 出现之后, 为了更方便地使用 GNU 工具链, 需要提供一个可执行 shell 脚本的运行环境从而可以在 shell 中调用MinGW 提供的那些工具如 gcc, make, linkr, 于是诞生了 MSYS(Minimal SYStem)。不过和 Cygwin 追求大而全的 POSIX 兼容系统不同, 其中间层 msys。dll 只提供基本的 POSIX API。因此MSYS可以看做是 Cygwin 的简化版, 但是因为一般 MSYS 都集成了MinGW, 所以当使用MSYS来构建应用程序时如果不使用一些特殊的 POSIX API 时, 比如 fork, mmap 其实就是在使用 MinGW 编译代码, 其程序是通过直接调用 Windows API 编译的, 所以可以不需要依赖任何中间层和第三方 DLL 库, 也就是说, 这时 MSYS 在这个编译过程只是作为一个辅助工具箱来使用。

    总结: MSYS 环境虽然也像 Cygwin 一样提供 POSIX API, 但是因为本着注重 Minimal (最小化) 的原则, 其只提供了最基本的 API, 其兼容性相对于 Cygwin 较差, 但相对于庞大的 Cygwin, 结合 MinGW 的 MSYS 可以编译不依赖于中间层 DLL 的应用程序,执行效率也更高,这个过程 MSYS 就相当于一个工具箱而已了。

    MinGW-w64

    可能是由于维护 MinGW 的人员工作太过于繁忙, 或是其他原因,MinGW 在后来更新速度异常缓慢,而且当初从 ming32 改名为 MinGW, 去掉 32 是为了避免它暗示仅限于生成32位二进制文件, 这就意味着在创建项目的时候开发人员还考虑到将来会更新 64 位版本, 但是直到现在, MinGW 仍然只支持生成 32 位的 Windows 程序, 甚至开发人员以及不打算让其支持 64 位的程序了。

    2005 年,因为最初的 MinGW 项目没有及时更新其代码库,包括包括几个关键的新 API 和急需的 64 位支持,OneVision Software 就创建了一个 MinGW 分支, 并把它命名为 MinGW-w64, 这里的 w64 是 windows 64 位的意思, 代表着支持生成 Windows 64位程序的MinGW, 但不限于64位, MinGW-w64 可以生成 32 位或 64 位的Windows 应用程序。

    完成 64位的支持和API更新后 OneVision 将 MinGW-w64 代码提交给MinGW原始项目维护人员,但他们由于怀疑OneVision使用非公开或专有信息而将其拒绝。之后的 2008年,OneVision 将代码捐赠给了其主要开发人员之一的 Kai Tietz, 其条件是该代码仍保持开源状态。由于许多原因,后来的MinGW-W64 项目的主要开发人员和联合创始人 Kai Tietz 决定不再尝试与 MinGW 进一步合作了。

    相对于 MinGW,MinGW-w64 提供了更完整的 Win32 API 实现, 但是,MinGW-w64 项目不提供官方的二进制构建,不过可以从开发人员的个人构建目录或者从相关但独立的项目(如 tdm-gcc 或 mingw-builds 或 msys2)中获取。

    总结: 因为 MinGW 更新缓慢以及不支持生成 Windows 64 位系统程序, 这才诞生了 MinGW-w64, 因此可以说 MinGW-w64 就是 MinGW 的升级版, 是基于 MinGW 的一个分支, 所以功能和 MinGW 一样,生成的程序是通过直接调用 Windows API 编译的而不需要中间层。

    MYSYS2

    MSYS2 (Minimal SYStem 2) 是对MSYS的独立重写,和 MinGW-w64 的诞生情况基本一致,因为 MSYS 太老了, 更新缓慢, 这才有了 MSYS2,不过, 它是基于现代 Cygwin 和 MinGW-w64,它的作用与以前的 MSYS 在 MinGW 中所起的作用相同。

    作为项目,Cygwin 和 MSYS2 有着明显不同的目标。

    Cygwin 试图为 Windows 带来一个与 POSIX 兼容的环境,这样在 Unices 上运行的大多数软件都可以在 Cygwin 上构建和运行,而无需进行任何重大修改。Cygwin 提供了大量包含此类软件的软件包,以及用于开发这些软件的库。

    MSYS2 试图为构建本机 Windows 软件提供环境。MSYS2 提供了包含此类软件的大量软件包,以及用于开发这些软件的库。由于该软件的很大一部分使用 GNU 构建工具,而 GNU 构建工具与 Unix 紧密耦合,因此该环境也与 POSIX 兼容,并且实际上是基于 Cygwin 的。

    MSYS2 提供了运行 AutoTools 和其他构建系统所需的最小外壳,这些构建系统从互联网上从不同的存储库获取软件源代码,并对其进行配置和构建。外壳和核心工具的存在主要是为了允许移植 Unix 程序在 Windows 上本地运行(即不需要 POSIX 模拟层)。MSYS2 不会在必要时重复 Cygwin 的工作,因此提供的 POSIX 仿真软件的数量非常少。

    MSYS2 使用 Pacman(出自 Arch Linux) 来管理其软件包,并附带三个不同的软件包存储库:

    总结: MSYS2 可看做是 MSYS 的升级版,它的作用与以前的 MSYS 在 MinGW 中所起的作用相同,并且基于 MinGW-w64, 因此可以编译运行 32 位和 64 位的程序。同时 MSYS2 使用 pacman 来管理软件包, 并且包含三个不同的软件包存储库,这意味着我们可以在不同的软件存储库之间切换。

    MSYS2 使用

    安装后生成三个快捷图标:

    msys2_shell.cmd 选项

    $ msys2_shell.cmd -help
    PS C:\msys64> .\msys2_shell.cmd -help
    Usage:
        msys2_shell.cmd [options] [login shell parameters]
    
    Options:
        -mingw32 | -mingw64 | -ucrt64 | -clang64 | -msys[2]   Set shell type
        -defterm | -mintty | -conemu                            Set terminal type
        -here                            Use current directory as working
                                         directory
        -where DIRECTORY                 Use specified DIRECTORY as working
                                         directory
        -[use-]full-path                 Use full current PATH variable
                                         instead of trimming to minimal
        -no-start                        Do not use "start" command and
                                         return login shell resulting
                                         errorcode as this batch file
                                         resulting errorcode
        -shell SHELL                     Set login shell
        -help | --help | -? | /?         Display this help and exit
    
    Any parameter that cannot be treated as valid option and all
    following parameters are passed as login shell command parameters.
    
    参数 说明
    -here 使 MSYS2 环境打开后立刻进入当前命令执行的环境,则默认会进入 HOME 目录
    -where + 指定目录 使 MSYS2 环境打开后进入指定文件夹
    -[use-]full-path 将整个 Windows 的 PATH 添加到 MSYS2 环境中(默认是把 Windows 下的 PATH 环境给部分屏蔽掉的,只继承一部分)
    -no-start 不需要再启动终端程序而是直接在当前终端进入 MSYS2 环境

    需要注意的是: 在 cmd 里进入 MSYS2 环境需要把终端类型设置成 -defterm 因为 MSYS2 默认使用的是 mintty 终端, 因此没有 -defterm 它会先打开 mintty 终端,然后执行 no-start 参数, 这不是我们想要的结果。

    msys2_shell.cmd -defterm -no-start
    

    集成到 VSCode 的终端

    setting.json 中添加:

    "terminal.integrated.shell.windows":"msys2_shell.cmd",
    "terminal.integrated.shellArgs.windows":["-defterm", "-mingw64", "-no-start", "-here"],
    

    设置 HOME 目录

    修改 msys2_shell.cmd 脚本,在文件较前的位置添加:

    set "HOME=指定目录"

    pacman 包管理

    MSYS2 提供了非常方便的 pacman 包管理工具,这个工具来自于 ArchLinux,因此各种命令参数都是通用的。不过由于 MSYS2 提供了三个运行环境,因此 pacman 管理的软件包也分三个来源,这三个源分别由一下三个文件管理:

    设置成国内的源:

    编辑 /etc/pacman.d/mirrorlist.mingw32 ,在文件开头添加:
    Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/i686 
    
    编辑 /etc/pacman.d/mirrorlist.mingw64 ,在文件开头添加:
    Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/x86_64 
    
    编辑 /etc/pacman.d/mirrorlist.msys ,在文件开头添加:
    Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/msys/$arch
    
    然后执行 pacman -Sy 刷新软件包数据即可。
    

    因为 pacman 同时管理三个环境的软件源,因此在安装卸载等操作时需要提供完整的软件包名,如果不是完整的软件包名称,则 pacman 默认操作的是 msys 环境下的软件, 例如 gcc,三个环境的名称分别是:

    MSYS: gcc
    mingw64: mingw-w64-x86_64-gcc
    mingw32: mingw-w64-i686-gcc
    

    常用命令

    pacman -S xxx                          # 安装某个软件
    pacman -Ss xxx                         # 查看某个软件
    pacman -Sl | grep -E "mingw64.*opencv" # 查询软件包
    pacman -R xxx                          # 删除某个软件
    

    © 2022-2024 留校察看 liuxocakn 保留所有权利 All Rights Reserved
    蜀ICP证2022022862号-1 川公网安备51010702003077号

    自 2024-04-23 22:54 之后访问量: 66160